<!--
  选择控件
  两个回调函数  callback 点击确定 close 点击关闭
-->
<template>
  <span class="avicit-select-box" @click="openSelect">
    <slot />
    <a-input
      v-if="!$slots.default"
      :value="inputExtra.length > 0 && select.nameAndExtra ? select.nameAndExtra : select.names"
      :title="inputExtra.length > 0 && select.nameAndExtra ? select.nameAndExtra : select.names"
      :disabled="disabled"
      :placeholder="placeholder"
      :auto-focus="autoFocus"
      readonly
      @change.prevent="handleChange"
      @click="inputClick"
      @blur="inputBlur"
      @focus="inputFocus"
    >
      <template #suffix>
        <avic-icon v-if="type === 'userSelect'" svg="UserOutlined" color="#86909c" />
        <avic-icon v-if="type === 'deptSelect' || type === 'orgSelect'" svg="PartitionOutlined" color="#86909c" />
        <avic-icon v-if="type === 'roleSelect'" svg="avic-contacts-line" color="#86909c" />
        <avic-icon v-if="type === 'groupSelect'" svg="TeamOutlined" color="#86909c" />
        <avic-icon
          v-if="type === 'positionSelect'"
          svg="avic-account-box-line"
          color="#86909c"
          style="font-size: 15px; height: 14px; line-height: 1"
        />
      </template>
    </a-input>
    <NoFormStatus>
      <!--选人-->
      <UserSelect
        v-if="type === 'userSelect' && ready"
        v-model:show="showApprove"
        :name="name"
        :title="title"
        :title-tips="titleTips"
        :search-placeholder="searchPlaceholder"
        :select-model="selectModel"
        :max-select="localMaxSelect"
        :default-value="internaldefaultValue"
        :model-change="select"
        :tab-show="tabShow"
        :view-scope="viewScope"
        :default-org-id="internalDefaultOrgId"
        :secret-level="secretLevel"
        :user-secret-level="userSecretLevel"
        :default-load-dept-id="defaultLoadDeptId"
        :default-load-group-id="defaultLoadGroupId"
        :default-load-role-id="defaultLoadRoleId"
        :default-load-position-id="defaultLoadPositionId"
        :view-system-user="viewSystemUser"
        :user-url="userUrl"
        :method-type="methodType"
        :user-search-url="userSearchUrl"
        :dept-tab-expand-level="deptTabExpandLevel"
        :search-num-limit="searchNumLimit"
        :custom-param="customParam || {}"
        :custom-search-param="customSearchParam || {}"
        :user-select-tabs="userSelectTabs"
        :get-init-user-info-url="getInitUserInfoUrl"
        :get-init-user-info-method="getInitUserInfoMethod"
        :more-user-info="moreUserInfo"
        :show-more-user-info="showMoreUserInfo"
        :filter-user="filterUser"
        :input-extra="inputExtra"
        :check-childen-node="checkChildenNode"
        :view-type="viewType"
        @defaultBack="defaultBack"
        @callBack="confirm"
        @close="close"
      >
        <template v-slot:moreInfo="{ userSideInfo }">
          <slot name="moreInfo" :user-side-info="userSideInfo" />
        </template>
      </UserSelect>
      <!--选部门-->
      <DeptSelect
        v-if="type === 'deptSelect' && ready"
        v-model:show="showApprove"
        :name="name"
        :title="title"
        :title-tips="titleTips"
        :search-placeholder="searchPlaceholder"
        :select-model="selectModel"
        :max-select="localMaxSelect"
        :default-value="internaldefaultValue"
        :model-change="select"
        :view-scope="viewScope"
        :default-org-id="internalDefaultOrgId"
        :default-load-dept-id="defaultLoadDeptId"
        :dept-level="deptLevel"
        :view-system-dept="viewSystemDept"
        :dept-url="deptUrl"
        :method-type="methodType"
        :dept-search-url="deptSearchUrl"
        :dept-expand-level="deptExpandLevel"
        :custom-param="customParam || {}"
        :check-strictly="checkStrictly"
        :custom-search-param="customSearchParam || {}"
        :more-dept-info="moreDeptInfo"
        :show-more-dept-info="showMoreDeptInfo"
        :org-checkable="orgCheckable"
        @defaultBack="defaultBack"
        @callBack="confirm"
        @close="close"
      />
      <!--选角色-->
      <RoleSelect
        v-if="type === 'roleSelect' && ready"
        v-model:show="showApprove"
        :name="name"
        :title="title"
        :title-tips="titleTips"
        :search-placeholder="searchPlaceholder"
        :select-model="selectModel"
        :max-select="localMaxSelect"
        :default-value="internaldefaultValue"
        :model-change="select"
        :view-scope="viewScope"
        :app-id="appId"
        :default-org-id="internalDefaultOrgId"
        :org-id="orgId"
        :role-url="roleUrl"
        :role-method-type="roleMethodType"
        :custom-param="customParam || {}"
        @defaultBack="defaultBack"
        @callBack="confirm"
        @close="close"
      />
      <!--选群组-->
      <GroupSelect
        v-if="type === 'groupSelect' && ready"
        v-model:show="showApprove"
        :name="name"
        :title="title"
        :title-tips="titleTips"
        :search-placeholder="searchPlaceholder"
        :select-model="selectModel"
        :max-select="localMaxSelect"
        :default-value="internaldefaultValue"
        :model-change="select"
        :view-scope="viewScope"
        :app-id="appId"
        :default-org-id="internalDefaultOrgId"
        :org-id="orgId"
        :group-url="groupUrl"
        :group-method-type="groupMethodType"
        @defaultBack="defaultBack"
        @callBack="confirm"
        @close="close"
      />
      <!--选岗位-->
      <PositionSelect
        v-if="type === 'positionSelect' && ready"
        v-model:show="showApprove"
        :name="name"
        :title="title"
        :title-tips="titleTips"
        :search-placeholder="searchPlaceholder"
        :select-model="selectModel"
        :max-select="localMaxSelect"
        :default-value="internaldefaultValue"
        :model-change="select"
        :view-scope="viewScope"
        :app-id="appId"
        :default-org-id="internalDefaultOrgId"
        :org-id="orgId"
        :position-url="positionUrl"
        :position-method-type="positionMethodType"
        @defaultBack="defaultBack"
        @callBack="confirm"
        @close="close"
      />
      <!-- 选组织-->
      <OrgSelect
        v-if="type === 'orgSelect' && ready"
        ref="avicCommonSelectOrgSelect"
        v-model:show="showApprove"
        :name="name"
        :title="title"
        :title-tips="titleTips"
        :search-placeholder="searchPlaceholder"
        :select-model="selectModel"
        :max-select="localMaxSelect"
        :default-value="internaldefaultValue"
        :model-change="select"
        :view-scope="viewScope"
        :default-org-id="internalDefaultOrgId"
        :org-id="orgId"
        :org-url="orgUrl"
        :org-search-url="orgSearchUrl"
        :method-type="orgMethodType"
        :custom-param="customParam || {}"
        :custom-search-param="customSearchParam || {}"
        :check-strictly="checkStrictly"
        @defaultBack="defaultBack"
        @callBack="confirm"
        @close="close"
      />
    </NoFormStatus>
  </span>
</template>
<script setup lang="ts">
import { Form } from 'ant-design-vue';
import { NoFormStatus } from 'ant-design-vue/es/form/FormItemContext';
import UserSelect from './UserSelect.vue';
import DeptSelect from './DeptSelect.vue';
import RoleSelect from './RoleSelect.vue';
import GroupSelect from './GroupSelect.vue';
import PositionSelect from './PositionSelect.vue';
import OrgSelect from './OrgSelect.vue';
import { getDeptAndPosition, getRoles, getOrg } from './api';
import { useUserStore } from '@/store/user';
import { settings } from '@/settings';

const props = defineProps({
  /** 选择类型，用户：userSelect，部门：deptSelect，角色：roleSelect，群组： groupSelect，岗位：positionSelect */
  type: {
    type: String as PropType<'userSelect' | 'deptSelect' | 'roleSelect' | 'groupSelect' | 'positionSelect' | 'orgSelect' | ''>,
    required: false,
    default: 'deptSelect'
  },
  /** 是否禁止输入 */
  disabled: { type: Boolean, required: false, default: false },
  /** 输入框是否自动获取焦点 */
  autoFocus: { type: Boolean, required: false, default: false },
  /** 输入框提示 */
  placeholder: { type: String, required: false, default: '' },
  /** 右侧列表已选标题文案 */
  name: { type: String, default: undefined },
  /** 标题 */
  title: { type: String, default: undefined },
  /** 弹窗标题中附加的辅助提示信息 */
  titleTips: { type: String, default: undefined },
  /** 搜索提示 */
  searchPlaceholder: { type: String, default: undefined },
  /** 单选 single ，多选 multi */
  selectModel: { type: String as PropType<'single' | 'multi'>, required: false, default: 'single' },
  /** 多选最多选择人数 */
  maxSelect: { type: Number, required: false, default: 0 },
  /** 字段长度,用于计算最多选人个数 */
  fieldLength: { type: Number, required: false, default: 0 },
  /** 默认值 */
  defaultValue: { type: String, required: false, default: null },
  /** 输入框中默认显示内容，通常用于编辑页面的回填 */
  defaultShowValue: { type: String, required: false, default: null },
  /** 返回数据 */
  value: { type: String, required: false, default: null },
  /** 组织范围 参数值: 当前组织:currentOrg, 含兼职组织:allowAcross：, 所有组织:all */
  viewScope: { type: String, required: false, default: '' },
  /** 应用id */
  appId: { type: String, required: false, default: '' },
  /** 默认加载指定组织下的数据 */
  defaultOrgId: { type: String, required: false, default: '' },
  /** 组织id */
  orgId: { type: String, required: false, default: '' },
  /** 默认加载部门id */
  defaultLoadDeptId: { type: String, required: false, default: '' },
  /** 默认加载群组id */
  defaultLoadGroupId: { type: String, required: false, default: '' },
  /** 默认加载角色id */
  defaultLoadRoleId: { type: String, required: false, default: '' },
  /** 默认加载岗位id */
  defaultLoadPositionId: { type: String, required: false, default: '' },
  /** 请求类型 */
  methodType: { type: String, required: false, default: 'post' },
  /** 用户请求接口地址 */
  userUrl: { type: String, required: false, default: '/appsys/common/select/getUserSelectList/v1' },
  /** 用户搜索请求接口地址 */
  userSearchUrl: {
    type: String,
    required: false,
    default: '/appsys/common/select/getUserSelectList/v1'
  },
  /** 部门请求接口地址 */
  deptUrl: { type: String, required: false, default: '/appsys/common/select/getDeptSelectList/v1' },
  /** 部门搜索请求接口地址 */
  deptSearchUrl: {
    type: String,
    required: false,
    default: '/appsys/common/select/getDeptSelectList/v1'
  },
  /** 自定义参数 */
  customParam: { type: Object, default: null },
  /** 自定义搜索参数 */
  customSearchParam: { type: Object, default: null },
  /** 是否默认选中当前登录用户 */
  defaultSelectSessionUser: { type: Boolean, required: false, default: false },
  /** 角色请求接口url */
  roleUrl: { type: String, default: '/appsys/common/select/getInitRoleInfo/v1' },
  /** 角色请求接口method */
  roleMethodType: { type: String, default: 'post' },
  /** 群组请求接口url */
  groupUrl: { type: String, default: '/appsys/common/select/getInitGroupInfo/v1' },
  /** 群组请求接口method */
  groupMethodType: { type: String, default: 'post' },
  /** 岗位请求接口url */
  positionUrl: { type: String, default: '/appsys/common/select/getInitPositionInfo/v1' },
  /** 岗位请求接口method */
  positionMethodType: { type: String, default: 'post' },
  /** 组织请求接口url */
  orgUrl: { type: String, default: '/appsys/common/select/getOrgSelectList/v1' },
  /** 组织请求接口method */
  orgMethodType: { type: String, default: 'post' },
  /** 组织搜索请求接口url */
  orgSearchUrl: {
    type: String,
    required: false,
    default: '/appsys/dept/DeptRest/getTreeTableDataOnOrgManagerByKeyword/v1'
  },
  /** 自定义初始化用户信息请求地址 */
  getInitUserInfoUrl: { type: String, default: '/appsys/common/select/getSelectedUserInfo/v1' },
  /** 选人获取初始化部门信息请求类型 */
  getInitUserInfoMethod: { type: String, default: 'post' },
  /** 是否显示无效部门 */
  viewSystemDept: { type: Boolean },
  /** 选部门初始展开层级 */
  deptExpandLevel: { type: Number, default: 0 },
  /** 部门最大展开层级 */
  deptLevel: { type: Number, default: null },
  /** 是否展示无效用户 */
  viewSystemUser: { type: Boolean },
  /** 选人-文档密级过滤 */
  secretLevel: { type: String, default: '' },
  /** 选人-人员密级过滤，只显示人员密级高于参数指定密级的用户 */
  userSecretLevel: { type: String, default: '' },
  /** 选人时是否显示tab */
  tabShow: { type: Boolean },
  /** 选人的部门tab页初始展开层级 */
  deptTabExpandLevel: { type: Number, default: 0 },
  /** 选人关键字查询时最大用户数限制 */
  searchNumLimit: { type: Number, default: 0 },
  /** 获取初始化角色的组织信息请求地址 */
  getInitRoleInfoUrl: { type: String, default: '/appsys/common/select/getSelectedRoleInfo/v1' },
  /** 获取初始化角色的组织信息请求类型 */
  getInitRoleInfoMethod: { type: String, default: 'post' },
  /** 获取初始化群组的组织信息请求地址 */
  getInitGroupInfoUrl: { type: String, default: '/appsys/common/select/getSelectedGroupInfo/v1' },
  /** 获取初始化群组的组织信息请求类型 */
  getInitGroupInfoMethod: { type: String, default: 'post' },
  /** 获取初始化岗位的组织信息请求地址 */
  getInitPositionInfoUrl: { type: String, default: '/appsys/common/select/getSelectedPositionInfo/v1' },
  /** 获取初始化岗位的组织信息请求类型 */
  getInitPositionInfoMethod: { type: String, default: 'post' },
  /** 用户可选择的维度 */
  userSelectTabs: {
    type: Array,
    default: () => ['dept', 'group', 'role', 'position']
  },
  /** 表单控制窗口是否显示 */
  showSelect: { type: Boolean, default: true },
  /** 人员额外展示信息 */
  moreUserInfo: { type: Array, default: () => ['deptid', 'deptname', 'loginName', 'no', 'secretLevel', 'deptNamePath', 'orgName'] },
  /** 是否展示人员附加信息 */
  showMoreUserInfo: { type: [Boolean, Array], default: settings.commonSelectExtends.showMoreUserInfo },
  /** 展示部门的附加信息,可选展示 */
  moreDeptInfo: { type: Array, default: () => ['orgName', 'deptNamePath'] },
  /** 是否展示部门附加信息 */
  showMoreDeptInfo: { type: [Boolean, Array], default: settings.commonSelectExtends.showMoreDeptInfo },
  /** 输入框中是否展示额外信息,需选择moreDeptInfo 中配置的数据 */
  inputExtra: { type: Array, default: () => [] },
  /** 树节点选中是否完全受控(不级联) */
  checkStrictly: { type: Boolean, default: false },
  /** 根据业务需要过滤可选人员数据的接口(sync) */
  filterUser: { type: Function, default: null },
  /** 部门选择中是否可选组织节点，仅type=deptSelect时生效 */
  orgCheckable: { type: Boolean, default: false },
  /** check时选中孙子节点,打开时会层层异步加载子节点的子节点，关闭时只加载一层子节点 */
  checkChildenNode: { type: Boolean, default: false },
  /** 选人-用户、角色、群组、岗位三个维度待选区的展示视图类型 table tree  */
  viewType: { type: String, default: settings.commonSelectExtends.viewType }
});
const showApprove = ref(false); // 窗口是否显示
const localMaxSelect = ref(0);
const internalDefaultOrgId = ref('0'); // 默认选中组织id
const ready = ref(true);
const formItemContext = Form.useInjectFormItemContext();
const select = reactive<any>({ ids: '', names: '' });
let internaldefaultValue = reactive<any>({ ids: '', names: '' }); // 默认选中值
watch(
  () => props.fieldLength,
  (newValue) => {
    const idLength = 33; // 每一个用户id的长度
    localMaxSelect.value = parseInt((newValue + 1) / idLength);
  },
  { immediate: true }
);
watch(
  () => props.maxSelect,
  (newValue) => {
    localMaxSelect.value = newValue;
  },
  { immediate: true }
);
watch(
  () => props.value,
  (newValue) => {
    if (!newValue) {
      select.ids = '';
      select.names = '';
    } else {
      select.ids = newValue;
    }
  },
  { immediate: true }
);
watch(
  () => props.defaultShowValue,
  (newValue) => {
    select.names = newValue;
  },
  { immediate: true }
);
watch(
  () => props.defaultValue,
  (newValue: any, oldValue: any) => {
    if (!newValue) {
      select.ids = '';
      select.names = '';
    } else if (JSON.stringify(newValue) !== JSON.stringify(oldValue)) {
      select.ids = newValue.ids;
      select.names = newValue.names;
      internaldefaultValue.ids = newValue.ids;
      internaldefaultValue.names = newValue.names;
      setDefaultAttr(newValue);
      setDefaultExtra(props.defaultValue);
    }
  },
  { immediate: true }
);

watch(
  () => props.defaultOrgId,
  (newValue) => {
    internalDefaultOrgId.value = newValue;
  },
  { immediate: true }
);
watch(
  () => props.type,
  () => {
    ready.value = false;
    select.ids = '';
    select.names = '';
  }
);
onBeforeMount(() => {
  if (props.defaultOrgId) {
    internalDefaultOrgId.value = props.defaultOrgId;
  }
  if (select.ids && props.defaultSelectSessionUser) {
    selectSessionUser();
  }
  if (props.defaultShowValue) {
    select.names = props.defaultShowValue;
  }
});
const $emit = defineEmits(['change', 'update:value', 'input', 'callback', 'close', 'click', 'blur', 'focus']);

// 禁止输入内容
function handleChange() {
  // 输入时打开弹框
  if (!props.disabled && !showApprove.value && props.showSelect) {
    showApprove.value = true;
  }
}

// 打开对应弹窗
function openSelect() {
  if (!props.disabled && props.showSelect) {
    showApprove.value = true;
  }
}

// 默认值回填
function defaultBack(value) {
  select.ids = value.ids;
  select.names = value.names;
}

// 点击确认
function confirm(value, selectRows = []) {
  select.ids = value.ids;
  select.names = value.names;
  // 设置部门全路径数据
  setNameAndExtra(value, selectRows);
  // 双向绑定
  $emit('input', value?.ids);
  // 空值也提交事件，以便清空表单项
  $emit('update:value', value?.ids);
  $emit('change', value?.ids);
  $emit('callback', value, selectRows);
  // 触发表单字段的change校验
  formItemContext?.onFieldChange && formItemContext.onFieldChange();
  if (showApprove.value) {
    showApprove.value = false;
  }
}
/** 设置部门全路径数据 */
function setNameAndExtra(value, selectRows) {
  if (['deptSelect', 'userSelect'].includes(props.type) && props.inputExtra.length > 0 && value.names) {
    select.nameAndExtra = value.names
      .split(';')
      .map((item, i) => {
        const extarInfo: any = props.inputExtra.reduce((pre: any, key: string) => {
          if (selectRows[i]) {
            pre.push(selectRows[i].attributes[key]);
          }
          return pre;
        }, []);
        return `${item}(${extarInfo.join('/')})`;
      })
      .join(';');
  }
}
/** 初始化时设置输入框默认附加信息 */
function setDefaultAttr(defaultValue: any) {
  if (props.type === 'userSelect') {
    if (typeof props.showMoreUserInfo == 'object') {
      props.showMoreUserInfo.forEach((key: string) => {
        defaultValue[key] ? (internaldefaultValue[key] = defaultValue[key]) : '';
      });
    } else if (props.showMoreUserInfo) {
      props.moreUserInfo.forEach((key: string) => {
        defaultValue[key] ? (internaldefaultValue[key] = defaultValue[key]) : '';
      });
    }
  }
  if (props.type === 'deptSelect') {
    if (typeof props.showMoreDeptInfo == 'object') {
      props.showMoreDeptInfo.forEach((key: string) => {
        defaultValue[key] ? (internaldefaultValue[key] = defaultValue[key]) : '';
      });
    } else if (props.showMoreDeptInfo) {
      props.moreDeptInfo.forEach((key: string) => {
        defaultValue[key] ? (internaldefaultValue[key] = defaultValue[key]) : '';
      });
    }
  }
}
/** 初始化时选人右侧数据默认附加信息 */
function setDefaultExtra(defaultValue) {
  if (['deptSelect', 'userSelect'].includes(props.type) && defaultValue.names) {
    const allAttributes = {};
    props.inputExtra.forEach((key: string) => {
      if (defaultValue[key]) {
        allAttributes[key] = defaultValue[key].split(';');
      }
    });
    select.nameAndExtra = defaultValue.names
      .split(';')
      .map((item, i) => {
        const extarInfo: any = props.inputExtra.reduce((pre: any, key: string) => {
          if (allAttributes[key] && allAttributes[key][i]) {
            pre.push(allAttributes[key][i]);
          }
          return pre;
        }, []);
        return `${item}(${extarInfo.join('/')})`;
      })
      .join(';');
  }
}
// 点击取消
function close() {
  $emit('close');
  showApprove.value = false;
}

function inputClick() {
  $emit('click', showApprove, select);
}

function inputBlur() {
  $emit('blur', showApprove, select);

  // 触发表单字段的blur校验
  formItemContext?.onFieldBlur && formItemContext.onFieldBlur();
}

function inputFocus() {
  $emit('focus', showApprove, select);
}

async function selectSessionUser() {
  const userStore = useUserStore();
  const user = userStore.currentUser;
  let dept = null;
  let role = null;
  let org = null;
  if (props.type === 'deptSelect' || props.type === 'positionSelect') {
    dept = await getDeptAndPosition(user.id);
  } else if (props.type === 'roleSelect') {
    role = await getRoles(user.id);
  } else if (props.type === 'orgSelect') {
    org = await getOrg(user.orgId);
  }
  if (user != null) {
    try {
      setTimeout(() => {
        let newSelect = {};
        if (select.ids.length === 0) {
          if (props.type === 'userSelect') {
            newSelect = { ids: user.id, names: user.username };
          } else if (props.type === 'deptSelect') {
            let ids = '';
            let names = '';
            if (dept && dept.length > 0) {
              dept.map((deptItem, i) => {
                if (i === 0) {
                  ids += deptItem.id;
                  names += deptItem.deptName;
                }
                return deptItem;
              });
            }
            newSelect = { ids, names };
          } else if (props.type === 'roleSelect') {
            const ids = role?.map(({ id }) => id)?.join?.(';') ?? '';
            const names = role?.map(({ roleName }) => roleName)?.join?.(';') ?? '';
            newSelect = { ids, names };
            internalDefaultOrgId.value = user.curOrgId;
          } else if (props.type === 'positionSelect') {
            let ids = '';
            let names = '';
            if (dept && dept.length > 0) {
              dept.map((positionItem, i) => {
                if (i === 1) {
                  ids += positionItem.id;
                  names += positionItem.positionName;
                }
                return positionItem;
              });
            }
            newSelect = { ids, names };
          } else if (props.type === 'orgSelect') {
            let ids = '';
            let names = '';
            if (org.result) {
              ids = org.result.orgId;
              names = org.result.orgName;
            }
            newSelect = { ids, names };
          }
          internaldefaultValue = reactive(select);
          if (newSelect != null) {
            confirm(newSelect);
          }
        }
      }, 500);
    } catch (error) {
      console.error(error);
    }
  }
}
defineExpose({
  select,
  openSelect
});
</script>
<style lang="less">
@import './style/base';
</style>
